#include "ledControl.h"
#include "../Global/GlobalDefs.hpp"

#include "WS2812FX-1.4.2/WS2812FX.h"
#define LED_COUNT 2

//#define PRINT_MODE

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

long myParseMode3(const char* commandIn);
long myParseColor8(const char* commandIn);
long myParseSpeed6(const char* commandIn);
uint8_t myParseOption3(const char* commandIn);

enum LedMode {
	undefined,
	// not allow any change 
	idle,
	identify,
	heatUp,
	heatHold,
	coolDown,
	coolHold,
	error
} _curMode;
bool _isLocked = false;

int LedControl::init() {
	ws2812fx.init();
	ws2812fx.start();
	_curMode = undefined;
	_isLocked = false;
	setModeIdle();
	return 1;
}

int LedControl::service() {
	ws2812fx.service();
	return 1;
}

// {mode3}{color8}{speed6}{option3}
// [1,3]  [6,13]  [16,21] [24,26]
int LedControl::setStyle(const char* commandIn) {
	ws2812fx.resetSegments();
	ws2812fx.setSegment(0, 0, LED_COUNT - 1);

	long mode3 = myParseMode3(commandIn);
	if (mode3 >= 0) {
		ws2812fx.setMode(mode3);
		Serial.print("Mod{" + String(mode3) + "}");
	}
	long color8 = myParseColor8(commandIn);
	if (color8 > 0) {
		ws2812fx.setColor(color8);
		Serial.print("Clr{" + String(color8) + "}");
	}
	long speed6 = myParseSpeed6(commandIn);
	if (speed6 > 0) {
		ws2812fx.setSpeed(speed6);
		Serial.print("Spd{" + String(speed6) + "}");
	}

	uint8_t option3 = myParseOption3(commandIn);
	ws2812fx.setOptions(0, option3);
	Serial.print("Opt{" + String(option3) + "}");

	Serial.print("\r\n");
	Serial.flush();
	return 1;
}

int LedControl::lockModes() {
	_isLocked = true;
	return 1;
}

int LedControl::unlockModes() {
	_isLocked = false;
#ifdef PRINT_MODE
	Serial.println("unlock");
#endif
	return 1;
}

// rainbow
int LedControl::setModeIdle() {
	if (_curMode == LedMode::idle) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::idle;
	ws2812fx.setMode(11);
	ws2812fx.setColor(255);
	// not effective
	ws2812fx.setSpeed(3000);
#ifdef PRINT_MODE
	Serial.println("idle");
#endif
	return 1;
}

// fade white
int LedControl::setModeIdentify() {
	if (_curMode == LedMode::identify) {
		return 1;
	}
	_isLocked = true;
	_curMode = LedMode::identify;
	ws2812fx.setMode(15);
	ws2812fx.setColor(0xffffff);
	ws2812fx.setSpeed(1000);
#ifdef PRINT_MODE
	Serial.println("identify");
#endif
	return 1;
}

// fade orange
int LedControl::setModeHeatUp() {
	if (_curMode == LedMode::heatUp) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::heatUp;
	ws2812fx.setMode(15);
	ws2812fx.setColor(0xffA000);
	ws2812fx.setSpeed(1000);
#ifdef PRINT_MODE
	Serial.println("heatUp");
#endif
	return 1;
}

// scan orange
int LedControl::setModeHeatHold() {
	if (_curMode == LedMode::heatHold) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::heatHold;
	ws2812fx.setMode(13);
	ws2812fx.setColor(0xffA000);
	ws2812fx.setSpeed(2000);
#ifdef PRINT_MODE
	Serial.println("heatHold");
#endif
	return 1;
}

// fade blue
int LedControl::setModeCoolDown() {
	if (_curMode == LedMode::coolDown) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::coolDown;
	ws2812fx.setMode(15);
	ws2812fx.setColor(0x0000ff);
	ws2812fx.setSpeed(1000);
#ifdef PRINT_MODE
	Serial.println("coolDown");
#endif
	return 1;
}

// scan blue
int LedControl::setModeCoolHold() {
	if (_curMode == LedMode::coolHold) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::coolHold;
	ws2812fx.setMode(13);
	ws2812fx.setColor(0x0000ff);
	ws2812fx.setSpeed(2000);
#ifdef PRINT_MODE
	Serial.println("coolHold");
#endif
	return 1;
}

int LedControl::setModeError(bool lock) {
	if (_curMode == LedMode::error) {
		return 1;
	}
	if (_isLocked) {
		return 0;
	}
	_curMode = LedMode::error;
	_isLocked = lock;
	ws2812fx.setMode(13);
	ws2812fx.setColor(0xff0000);
	ws2812fx.setSpeed(1000);
#ifdef PRINT_MODE
	Serial.println("error");
#endif
	return 1;
}

// {mode3}{color8}{speed6}{option3}
// [1,3]  [6,13]  [16,21] [24,26]
long myParseMode3(const char* commandIn) {
	commandIn += 1;
	return atol(commandIn);
}

// {mode3}{color8}{speed6}{option3}
// [1,3]  [6,13]  [16,21] [24,26]
long myParseColor8(const char* commandIn) {
	commandIn += 6;
	return atol(commandIn);
}

// {mode3}{color8}{speed6}{option3}
// [1,3]  [6,13]  [16,21] [24,26]
long myParseSpeed6(const char* commandIn) {
	commandIn += 16;
	return atol(commandIn);
}

// {mode3}{color8}{speed6}{option3}
// [1,3]  [6,13]  [16,21] [24,26]
uint8_t myParseOption3(const char* commandIn) {
	commandIn += 24;
	return atoi(commandIn);
}
